﻿using System.Collections.Generic;
using Fruits.DataTable;
using Fruits.UI;
using Fruits.Utility;
using GameFramework.Event;
using GameFramework.Resource;
using TMPro;
using UnityGameFramework.Runtime;
using GameEntry = Fruits.Base.GameEntry;
using ProcedureOwner = GameFramework.Fsm.IFsm<GameFramework.Procedure.IProcedureManager>;
namespace Fruits.Procedure
{
    public class ProcedurePreload : ProcedureBase
    {
        /// <summary>
        /// TODO:考虑将此字段移到配置表
        /// </summary>
        public static readonly string[] DataTableNames =
        {
            "Scene",
            "Sound",
            "Music",
            "UIForm",
            "UISound",
        };

        private Dictionary<string, bool> m_LoadFlag = new();
        public override bool UseNativeDialog { get; } = true;
        
        
        protected override void OnEnter(ProcedureOwner procedureOwner)
        {
            base.OnEnter(procedureOwner);
            
            GameEntry.Event.Subscribe(LoadConfigSuccessEventArgs.EventId, OnLoadConfigSuccess);
            GameEntry.Event.Subscribe(LoadConfigFailureEventArgs.EventId, OnLoadConfigFailure);
            GameEntry.Event.Subscribe(LoadDataTableSuccessEventArgs.EventId, OnLoadDataTableSuccess);
            GameEntry.Event.Subscribe(LoadDataTableFailureEventArgs.EventId, OnLoadDataTableFailure);
            GameEntry.Event.Subscribe(LoadDictionarySuccessEventArgs.EventId, OnLoadDictionarySuccess);
            GameEntry.Event.Subscribe(LoadDictionaryFailureEventArgs.EventId, OnLoadDictionaryFailure);
            
            m_LoadFlag.Clear();
            PreloadResources();
        }

        protected override void OnUpdate(ProcedureOwner procedureOwner, float elapseSeconds, float realElapseSeconds)
        {
            base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);

            foreach (var loadFlag in m_LoadFlag)
            {
                if (!loadFlag.Value)
                    return;
            }

            int sceneID = 0;
            //  不是第一次登录
            if (GameEntry.Setting.HasSetting(Constant.Setting.FirstLogin))
            {
                
            }
            //  第一次登录
            else
            {
                sceneID = GameEntry.Config.GetInt(Constant.Scene.BgMeun);
            }

        }
        
        protected override void OnLeave(ProcedureOwner procedureOwner, bool isShutdown)
        {
            base.OnLeave(procedureOwner, isShutdown);
            
            GameEntry.Event.Unsubscribe(LoadConfigSuccessEventArgs.EventId, OnLoadConfigSuccess);
            GameEntry.Event.Unsubscribe(LoadConfigFailureEventArgs.EventId, OnLoadConfigFailure);
            GameEntry.Event.Unsubscribe(LoadDataTableSuccessEventArgs.EventId, OnLoadDataTableSuccess);
            GameEntry.Event.Unsubscribe(LoadDataTableFailureEventArgs.EventId, OnLoadDataTableFailure);
            GameEntry.Event.Unsubscribe(LoadDictionarySuccessEventArgs.EventId, OnLoadDictionarySuccess);
            GameEntry.Event.Unsubscribe(LoadDictionaryFailureEventArgs.EventId, OnLoadDictionaryFailure);
        }
        

        private void PreloadResources()
        {
            LoadConfig("DefaultConfig");
            foreach (string dataTableName in DataTableNames)
            {
                LoadDataTable(dataTableName);
            }
            LoadDictionary("Default");
            LoadFont("MainFont");
        }

        private void LoadConfig(string configName)
        {
            string configAssetName = AssetUtility.GetConfigAsset(configName, false);
            m_LoadFlag.Add(configAssetName, false);
            GameEntry.Config.ReadData(configAssetName, this);
        }


        private void LoadDataTable(string dataTableName)
        {
            string dataTableAssetName = AssetUtility.GetConfigAsset(dataTableName, false);
            m_LoadFlag.Add(dataTableName, false);
            GameEntry.DataTable.LoadDataTable(dataTableName, dataTableAssetName, this);
        }

        /// <summary>
        /// 加载多语言
        /// </summary>
        private void LoadDictionary(string dictionaryName)
        {
            string dictionaryAssetName = AssetUtility.GetDictionaryAsset(dictionaryName, false);
            m_LoadFlag.Add(dictionaryName, false);
            GameEntry.Localization.ReadData(dictionaryAssetName, this);
        }


        private void LoadFont(string fontName)
        {
            m_LoadFlag.Add(GameFramework.Utility.Text.Format("Font.{0}", fontName), false);
            GameEntry.Resource.LoadAsset(AssetUtility.GetFontAsset(fontName), Constant.AssetPriority.FontAsset, new LoadAssetCallbacks(
                (assetName, asset, duration, userdata) =>
                {
                    m_LoadFlag[GameFramework.Utility.Text.Format("Font.{0}", fontName)] = true;
                    UGuiForm.SetMainFont((TMP_FontAsset)asset);
                    Log.Info("Load font '{0}' OK.", fontName);
                },
                (assetName, status, errorMessage, userdata) =>
                {
                    Log.Error("Can not load font '{0}' from '{1}' with error message '{2}'.", fontName, assetName, errorMessage);
                }
            ));
        }

        private void OnLoadConfigSuccess(object sender, GameEventArgs args)
        {
            LoadConfigSuccessEventArgs ne = (LoadConfigSuccessEventArgs)args;
            if (ne.UserData != this)
            {
                return;
            }

            m_LoadFlag[ne.ConfigAssetName] = true;
            Log.Info("Load config '{0}' OK.", ne.ConfigAssetName);
        }

        private void OnLoadConfigFailure(object sender, GameEventArgs e)
        {
            LoadConfigFailureEventArgs ne = (LoadConfigFailureEventArgs)e;
            if (ne.UserData != this)
                return;
            Log.Error("Can not load config '{0}' from '{1}' with error message '{2}'.", ne.ConfigAssetName, ne.ConfigAssetName, ne.ErrorMessage);
        }

        private void OnLoadDataTableSuccess(object sender, GameEventArgs e)
        {
            LoadDataTableSuccessEventArgs ne = (LoadDataTableSuccessEventArgs)e;
            if (ne.UserData != this)
                return;
            m_LoadFlag[ne.DataTableAssetName] = true;
            Log.Info("Load data table '{0}' OK.", ne.DataTableAssetName);
        }

        private void OnLoadDataTableFailure(object sender, GameEventArgs e)
        {
            LoadDataTableFailureEventArgs ne = (LoadDataTableFailureEventArgs)e;
            if (ne.UserData != this)
                return;
            Log.Error("Can not load data table '{0}' from '{1}' with error message '{2}'.", ne.DataTableAssetName, ne.DataTableAssetName, ne.ErrorMessage);
        }

        private void OnLoadDictionarySuccess(object sender, GameEventArgs args)
        {
            LoadDictionarySuccessEventArgs ne = (LoadDictionarySuccessEventArgs)args;
            if (ne.UserData != this)
                return;
            
            m_LoadFlag[ne.DictionaryAssetName] = true;
            Log.Info("Load dictionary '{0}' OK.", ne.DictionaryAssetName);
        }

        private void OnLoadDictionaryFailure(object sender, GameEventArgs e)
        {
            LoadDictionaryFailureEventArgs ne = (LoadDictionaryFailureEventArgs)e;
            if (ne.UserData != this)
                return;
            Log.Error("Can not load dictionary '{0}' from '{1}' with error message '{2}'.", ne.DictionaryAssetName, ne.DictionaryAssetName, ne.ErrorMessage);
        }

    }
}